#include "geometrydata.h"
#include "triangulation.h"
#include <stdio.h>
#include <string>
//=======================================================================
GeometryData::GeometryData()
{
    min_param = 0;
    max_param = 0;
    contour_started = false;
}

//=======================================================================
void GeometryData::clear()
{
    contour_started = false;
    points.clear();
    points.resize(0);
    triangles.clear();
    triangles.resize(0);
    contours.clear();
    contours.resize(0);
    edges.clear();
    edges.resize(0);

    min_param = 0;
    max_param = 0;
}

//=======================================================================
Point *GeometryData::addPoint(double x, double y, double param)
{
    Point *p = new Point(x,y,param, points.size());
    points.push_back(p);
    return p;
}

//=======================================================================

Edge * GeometryData::findEdge(Point *p1, Point *p2)
{
    //for (int i =edges.size()-1; i >=0 ; i--)
    //{
    //    if ((edges[i]->p1 == p1 && edges[i]->p2 == p2) || (edges[i]->p1 == p2 && edges[i]->p2 == p1) )
    //        return edges[i];
    //}
   Edge *e = edges_map[p1][p2];
   if (!e)
       e = edges_map[p2][p1];

   if (!e)
           return NULL;
   return e;
    //return NULL;
}

//=======================================================================
void GeometryData::addEdge(Point *p1, Point *p2, Triangle *t)
{
    Edge *e = findEdge(p1,p2);

    if (e == NULL)
    {
        e = new Edge(p1,p2);
        edges.push_back(e);
    }
    e->triangles.push_back(t);
    edges_map[p1][p2] = e;
    t->edges.push_back(e);
}

//=======================================================================
void GeometryData::autoBound()
{
    for (int i =0; i < edges.size(); i++)
    {
       Edge *e  = edges[i];
       if (e->type != Edge::NONE)
            continue;

       if (e->triangles.size() == 2)
           e->type = Edge::NONE;

       if (e->triangles.size() == 1)
           e->type = Edge::WALL;


    }
}

//=======================================================================
Triangle * GeometryData::addTriangle(int p1, int p2, int p3, int param)
{
    Triangle *t = new Triangle(points[p1], points[p2], points[p3], triangles.size(), param);
    points[p1]->triangles.push_back(t);
    points[p2]->triangles.push_back(t);
    points[p3]->triangles.push_back(t);
    addEdge(points[p1], points[p2], t);
    addEdge(points[p2], points[p3], t);
    addEdge(points[p3], points[p1], t);

    triangles.push_back(t);

    min_param = std::min(min_param, param);
    max_param = std::max(max_param, param);
    return t;
}

//=======================================================================
Contour * GeometryData::startContour(double param)
{
    printf("Starting countor\n");
    Contour *ct = new Contour;
    ct->param = param;
    contour_started = true;
    contours.push_back(ct);
    return ct;
}

//=======================================================================
void GeometryData::updateIndeces()
{
    for (int i = 0; i < points.size(); i++)
    {
        points[i]->index = i;
    }

    for (int i = 0; i < triangles.size(); i++)
    {
        triangles[i]->index = i;
    }
}

//=======================================================================
void GeometryData::triangulateContours(const std::string &algo)
{
    if (algo == "p2t")
    {
        triangulateContoursP2T(contours,&points,&triangles);
    }

    if (algo == "my")
    {
        triangulateContoursMy(contours,&points,&triangles);
    }
    data_type = GeometryData::TRIANGLES;
    printf("Triangles: %d\n",triangles.size());
    updateIndeces();
}

//=======================================================================
void GeometryData::sharpTriangulation(const std::string &algo)
{
    if (algo == "area")
    {
        sharpTriangulationByArea(&points,&triangles,0.01);
    }

    if (algo == "my")
    {
        //triangulateContoursMy(contours,&points,&triangles);
    }

    if (algo == "once")
    {
        sharpOnce(&points,&triangles);
    }


    data_type = GeometryData::TRIANGLES;
    printf("Triangles: %d\n",triangles.size());
    updateIndeces();
}


